%{
#include "TreeNode.h"
#define YYSTYPE TreeNode *
#include <string>

using namespace std;

extern int current_lineno ;
extern char *yytext;

int yylex();
int yyerror(const char *s);

static char saved_name[256]; /* for use in assignments */
static int saved_lineNo;  /* ditto */
extern TreeNode * root; /* stores syntax tree for later return */

%}

%token IF_T THEN ELSE END REPEAT UNTIL READ WRITE
%token ID NUM 
%token ASSIGN EQ LT PLUS MINUS TIMES OVER LPAREN RPAREN SEMI
%token ERROR 

%% /* Grammar for TINY */

program     : stmt_seq {root = $1; }
            ;
stmt_seq    : stmt_seq SEMI stmt {$1->children.push_back( $3);
                                $$ = $1;
                                   }
            | stmt  { $$=new_stmt_node();
                     $$->children.push_back( $1);
             }
            ;
stmt        : if_stmt { $$ = $1; }
            | repeat_stmt { $$ = $1; }
            | assign_stmt { $$ = $1; }
            | read_stmt { $$ = $1; }
            | write_stmt { $$ = $1; }
            | error  { $$ = NULL; }
            ;
if_stmt     : IF_T exp THEN stmt_seq END     
                 { 
                  $$ = new_if_stmt(current_lineno, $2, $4);
                 }
            | IF_T exp THEN stmt_seq ELSE stmt_seq END
                 { $$ = new_if_stmt(current_lineno, $2, $4, $6);
                 }
            ;
repeat_stmt : REPEAT stmt_seq UNTIL exp
                 { $$ = new_repeat_stmt(current_lineno, $2, $4);
                 }
            ;
assign_stmt : ID { $1=new_id(current_lineno, yytext);
               }
              ASSIGN exp
                 { 
                    $$ = new_assign_stmt(current_lineno, $1, $4);                
                 }
            ;
read_stmt   : READ ID
                 {
                  $$=new_read_stmt(current_lineno, new_id(current_lineno, yytext));
                 }
            ;
write_stmt  : WRITE exp
                 { 
                  $$=new_write_stmt(current_lineno, $2);
                 }
            ;
exp         : simple_exp LT simple_exp 
                 { 
                  $$ = new_exp(current_lineno, $1,LT,$3);
                 }
            | simple_exp EQ simple_exp
                 { 
                  $$=new_exp(current_lineno, $1,EQ,$3);
                 }
            | simple_exp { $$ =$1; }
            ;
simple_exp  : simple_exp PLUS term 
                 { 
                  $$=new_simple_exp(current_lineno, $1, PLUS, $3);
                 }
            | simple_exp MINUS term
                 { 
                  $$=new_simple_exp(current_lineno, $1, MINUS, $3);
                 } 
            | term { $$ = $1; }
            ;
term        : term TIMES factor 
                 { 
                  $$=new_term(current_lineno, $1, TIMES, $3);
                 }
            | term OVER factor
                 { 
                  $$=new_term(current_lineno, $1, OVER, $3);
                 }
            | factor { $$ = $1; }
            ;
factor      : LPAREN exp RPAREN
                 { $$ = $2; }
            | NUM
                 { 
                  $$=new_num(current_lineno, atoi(yytext));
                 }
            | ID {
                  $$=new_id(current_lineno, yytext);
                 }
            | error { $$ = NULL; }
            ;

%%

int yyerror(const char *s) {
     fprintf(stderr, "Error: %s at line %d near %s\n", s, current_lineno, yytext);
     return 0;
}

